package com.tca.spring.framework.learning.ioc.pre;

import com.tca.spring.framework.learning.ioc.beans.Student;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author zhouan
 * @Date 2021/1/29
 */
@Slf4j
public class PreStart {

    public static void main(String[] args) {

        reflectInjection();

        reflectAndAnnotationInjection();

    }

    /**
     * 通过反射和注解注入
     */
    private static void reflectAndAnnotationInjection() {
        School school = new School();
        Class<? extends School> clazz = school.getClass();
        Field[] declaredFields = clazz.getDeclaredFields();
        Arrays.asList(declaredFields).stream().forEach(field -> {
            try {
                AutowiredCustom annotation = field.getAnnotation(AutowiredCustom.class);
                if (annotation != null) {
                    // 使用字段Field方式直接注入
                    field.setAccessible(true);
                    field.set(school, field.getType().newInstance());
                }
            } catch (Exception e) {
                log.error("", e);
            }
        });
        log.info("reflectAndAnnotationInjection : school = {}", school);
    }

    /**
     * 通过反射直接注入
     */
    private static void reflectInjection() {
        School school = new School();
        Class<? extends School> clazz = school.getClass();
        Field[] declaredFields = clazz.getDeclaredFields();
        Arrays.asList(declaredFields).stream().forEach(field -> {
            try {
                // 使用方法Method对象调用注入
                String name = field.getName();
                Object newInstance = field.getType().newInstance();
                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1, name.length());
                Method method = clazz.getDeclaredMethod(methodName, field.getType());
                method.invoke(school, newInstance);
            } catch (Exception e) {
                log.error("", e);
            }
        });
        log.info("reflectInjection : school = {}", school);
    }


}


class School {

    @AutowiredCustom
    private Student student;


}